package com.bookrecomm.crawler.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.util.Random;

/**
 * HTTP请求工具类
 * 负责发送HTTP请求并获取响应内容
 */
@Slf4j
public class HttpUtil {
    // 常用User-Agent列表，模拟不同浏览器
    private static final String[] USER_AGENTS = {
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"
    };
    
    // 随机数生成器
    private static final Random RANDOM = new Random();
    
    // 请求配置
    private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom()
            .setConnectTimeout(5000)  // 连接超时时间
            .setSocketTimeout(10000)  // 读取超时时间
            .setConnectionRequestTimeout(3000)  // 从连接池获取连接的超时时间
            .build();
    
    /**
     * 发送GET请求并获取响应内容
     * @param url 请求URL
     * @return 响应内容字符串
     */
    public static String doGet(String url) {
        return doGet(url, "UTF-8");
    }
    
    /**
     * 发送GET请求并获取响应内容
     * @param url 请求URL
     * @param charset 字符编码
     * @return 响应内容字符串
     */
    public static String doGet(String url, String charset) {
        // 创建HttpClient对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建HttpGet请求
            HttpGet httpGet = new HttpGet(url);
            
            // 设置请求配置
            httpGet.setConfig(REQUEST_CONFIG);
            
            // 设置请求头，模拟浏览器行为
            httpGet.setHeader("User-Agent", getRandomUserAgent());
            httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
            httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
            httpGet.setHeader("Connection", "keep-alive");
            httpGet.setHeader("Upgrade-Insecure-Requests", "1");
            
            log.info("发送HTTP GET请求: {}", url);
            
            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                // 获取响应状态
                int statusCode = response.getStatusLine().getStatusCode();
                log.info("HTTP响应状态码: {}", statusCode);
                
                // 获取响应实体
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    // 转换响应内容为字符串
                    String result = EntityUtils.toString(entity, charset);
                    return result;
                }
            }
        } catch (Exception e) {
            log.error("HTTP请求失败: {}", url, e);
        }
        
        return null;
    }
    
    /**
     * 随机获取一个User-Agent
     * @return 随机User-Agent字符串
     */
    public static String getRandomUserAgent() {
        return USER_AGENTS[RANDOM.nextInt(USER_AGENTS.length)];
    }
    
    /**
     * 随机等待一段时间，避免频繁请求被封IP
     * @param minSeconds 最小等待秒数
     * @param maxSeconds 最大等待秒数
     */
    public static void randomSleep(int minSeconds, int maxSeconds) {
        try {
            int sleepTime = minSeconds * 1000 + RANDOM.nextInt((maxSeconds - minSeconds) * 1000);
            log.info("随机等待 {} 毫秒", sleepTime);
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
